package test.uis.screens;

import basemod.ReflectionHacks;
import basemod.abstracts.CustomScreen;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.evacipated.cardcrawl.modthespire.lib.SpireEnum;
import com.megacrit.cardcrawl.cards.AbstractCard;
import com.megacrit.cardcrawl.core.Settings;
import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
import com.megacrit.cardcrawl.helpers.input.InputHelper;
import com.megacrit.cardcrawl.screens.select.HandCardSelectScreen;
import com.megacrit.cardcrawl.ui.buttons.CardSelectConfirmButton;
import com.megacrit.cardcrawl.ui.buttons.PeekButton;
import test.monitors.SeaMonitor;
import test.patches.TagsPatch;
import test.uis.buttons.CustomButton;

import java.util.ArrayList;

public class SakiMoveScreen extends CustomScreen {
    public static class Enum {
        @SpireEnum
        public static AbstractDungeon.CurrentScreen SAKIMOVE_SCREEN;
        //HandCardSelectScreen
    }

    private AbstractCard draggedCard;
    public CustomButton confirmButton;
    public CustomButton resetButton;
    public AbstractCard hoveringCard;
    public boolean hasRelic;
    public boolean hasExchanged;
    public boolean hasChangedAndReleased;
    public ArrayList<SeaMonitor.Sea> seaCopy;
    private PeekButton peekButton;

    @Override
    public AbstractDungeon.CurrentScreen curScreen() {
        return Enum.SAKIMOVE_SCREEN;
    }

    private void open(String foo, AbstractCard bar) {
        prep();
        draggedCard=null;
        confirmButton = new CustomButton();
        confirmButton.show();
        confirmButton.enable();
        confirmButton.hb.move(Settings.WIDTH/3, Settings.HEIGHT/2);

        resetButton = new CustomButton();
        resetButton.show();
        resetButton.enable();
        resetButton.hb.move(2*Settings.WIDTH/3, Settings.HEIGHT/2);
        resetButton.buttonText="重置";

        hasRelic=false;
        hasExchanged=false;
        hasChangedAndReleased=false;
        for(AbstractCard c : AbstractDungeon.player.hand.group){
            if(TagsPatch.CardFieldPatch.hasAnchor.get(c)){
                c.isGlowing=false;
            }
        }
        seaCopy = SeaMonitor.deepCopy();
        this.peekButton = new PeekButton();
        this.peekButton.hideInstantly();
        this.peekButton.show();
    }

    @Override
    public void reopen() {

    }

    @Override
    public void close() {
        genericScreenOverlayReset();
        AbstractDungeon.overlayMenu.showCombatPanels();
    }

    @Override
    public void update() {
        this.peekButton.update();
        if(!PeekButton.isPeeking){
            updateHover();
            updateHoverLogic();
            updateDrag();
            updateButton();
            updateGlow();
        }
    }

    public void updateGlow(){
        for(AbstractCard c : AbstractDungeon.player.hand.group){
            if(TagsPatch.CardFieldPatch.hasAnchor.get(c)||hasChangedAndReleased){
                c.isGlowing=false;
            }else{
                c.isGlowing=true;
            }
        }
    }

    public boolean isCardHovered(AbstractCard c) {
        if(hasRelic) {
            return c.hb.hovered;
        }else{
            return c.hb.hovered&&!TagsPatch.CardFieldPatch.hasAnchor.get(c)&&!hasChangedAndReleased;
        }
    }

    public void updateHover(){
        for(int i=AbstractDungeon.player.hand.size() - 1; i>=0; i--){
            AbstractCard c=AbstractDungeon.player.hand.group.get(i);
            if(isCardHovered(c)) {
                hoveringCard = c;
                return;
            }

        }
        hoveringCard=null;
    }

    public void updateHoverLogic() {
        for(AbstractCard card:AbstractDungeon.player.hand.group) {
            card.update();
            card.hb.update();
            if (hoveringCard!=null&& hoveringCard.equals(card)) {
                card.hover();
                ReflectionHacks.setPrivate(card, AbstractCard.class, "hoverDuration",
                        (float) ReflectionHacks.getPrivate(card, AbstractCard.class, "hoverDuration")+Gdx.graphics.getDeltaTime());
                if ((float) ReflectionHacks.getPrivate(card, AbstractCard.class, "hoverDuration") > 0.2F && !Settings.hideCards) {
                    ReflectionHacks.setPrivate(card, AbstractCard.class, "renderTip",true);
                }
            } else {
                card.unhover();
            }
        }
    }

    private void updateButton() {
        this.confirmButton.update();
        this.resetButton.update();
        if (this.confirmButton.hb.clicked ) {
            this.confirmButton.hb.clicked = false;
            AbstractDungeon.closeCurrentScreen();
        }
        if (this.resetButton.hb.clicked ) {
            this.resetButton.hb.clicked = false;
            SeaMonitor.seaList.clear();
            for(int i=0;i<SeaMonitor.MAX_HAND_SIZE;i++){
                SeaMonitor.seaList.add(seaCopy.get(i).deepCopy());
            }
            SeaMonitor.sortHandCardGroup();
            AbstractDungeon.player.hand.refreshHandLayout();
            hasExchanged=false;
            hasChangedAndReleased=false;
        }
    }

    private void updateDrag() {
        if (InputHelper.justReleasedClickLeft) {
            draggedCard = null;
            AbstractDungeon.player.hand.refreshHandLayout();
            if(hasExchanged) {
                hasChangedAndReleased=true;
            }
        }

        for (int i = 0; i < AbstractDungeon.player.hand.group.size(); i++) {
            AbstractCard card = AbstractDungeon.player.hand.group.get(i);

            if (card == draggedCard) {
                handleDragging(card);
            } else if (card.equals(hoveringCard) && InputHelper.justClickedLeft) {
                startDragging(card);
            }
        }
    }


    private void startDragging(AbstractCard card) {
        draggedCard = card;
        InputHelper.justClickedLeft = false;
    }

    private void handleDragging(AbstractCard card) {
        card.target_x = InputHelper.mX;
        card.current_x = card.target_x;

        int index = AbstractDungeon.player.hand.group.indexOf(card);
        AbstractCard left= getFirstLeftUnAnchorCard(index);
        if(left!=null&&card.current_x<left.current_x) {
            exchangeCards(card,left);
        }

        AbstractCard right= getFirstRightUnAnchorCard(index);
        if(right!=null&&card.current_x>right.current_x) {
            exchangeCards(card,right);
        }
    }

    private AbstractCard getFirstLeftUnAnchorCard(int index){
        if(hasRelic) {
            if(index==0){
                return null;
            }
            return AbstractDungeon.player.hand.group.get(index - 1);
        }else{
            while(index-1>=0){
                if(TagsPatch.CardFieldPatch.hasAnchor.get(AbstractDungeon.player.hand.group.get(index-1))){
                    index--;
                }else{
                    return AbstractDungeon.player.hand.group.get(index-1);
                }
            }
            return null;
        }
    }

    private AbstractCard getFirstRightUnAnchorCard(int index){
        if(hasRelic) {
            if(index==AbstractDungeon.player.hand.group.size()){
                return null;
            }
            return AbstractDungeon.player.hand.group.get(index + 1);
        }else{
            while(index+1<=AbstractDungeon.player.hand.group.size()-1){
                if(TagsPatch.CardFieldPatch.hasAnchor.get(AbstractDungeon.player.hand.group.get(index+1))){
                    index++;
                }else{
                    return AbstractDungeon.player.hand.group.get(index+1);
                }
            }
            return null;
        }
    }

    private void exchangeCards(AbstractCard card1, AbstractCard card2) {
        SeaMonitor.swapCard(card1, card2);
        SeaMonitor.sortHandCardGroup();
        AbstractDungeon.player.hand.refreshHandLayout();
        hasExchanged=true;
    }

    @Override
    public void render(SpriteBatch sb) {
        AbstractDungeon.player.hand.render(sb);
        AbstractDungeon.overlayMenu.energyPanel.render(sb);
        if(!PeekButton.isPeeking){
            this.confirmButton.render(sb);
            this.resetButton.render(sb);
        }
        this.peekButton.render(sb);
        AbstractDungeon.overlayMenu.combatDeckPanel.render(sb);
        AbstractDungeon.overlayMenu.discardPilePanel.render(sb);
        AbstractDungeon.overlayMenu.exhaustPanel.render(sb);
    }

    @Override
    public void openingSettings() {
        AbstractDungeon.screen = curScreen();
    }

    private void prep() {
        AbstractDungeon.player.resetControllerValues();

        for(AbstractCard c : AbstractDungeon.player.hand.group) {
            c.unhover();
        }

        AbstractDungeon.topPanel.unhoverHitboxes();
        AbstractDungeon.player.releaseCard();
        AbstractDungeon.getMonsters().hoveredMonster = null;
        AbstractDungeon.isScreenUp = true;
        AbstractDungeon.screen = curScreen();
        AbstractDungeon.player.hand.stopGlowing();
        AbstractDungeon.player.hand.refreshHandLayout();
        AbstractDungeon.overlayMenu.showBlackScreen(0.75F);
    }
}